/*
* @Author: 窦子滨<zibin_5257@163.com>
* @Date: 2019-04-10
 */
package TcpPack

import (
	"base/common"
	"encoding/binary"
	"encoding/hex"
	"io"
	"strings"
)

//主动上传历史记录数据包

//解析主动上传历史记录规则
type HistoryPack struct {
	Count              int16       //数据单元个数
	ChargeMethod       int8        //单元1-充电方式
	ChargeMode         int8        //单元2-充电模式
	CardType           int8        //单元3-充电卡类型
	UserId             string      //单元4-用户号或者手机号，字符串格式，20字节，小于20字节后面补0
	CarVin             string      //单元5-汽车VIN码 17字节
	BeforeSurplusMoney float64     //6-充电前余额 xx.xx
	ChargeVoltage      float64     //单元7-充电电压 含1位小数 桩端电表读数
	ChargeCurrent      float64     //单元8-充电电流 含两位小数 桩端电表读数
	ChargeTime         int32       //单元9-充电时间 单位秒
	ChargeMoney        float64     //单元10-充电金额 2位小数
	ChargeAmount       float64     //单元11-充电电能 2位小数
	BeforeAmount       float64     //单元12-充电前电能 xx.xx
	StopAmount         float64     //单元13-充电结束后电能 xx.xx
	SurplusTime        int32       //单元14-剩余时间 仅限直流
	Soc                int8        //单元15-当前SOC 仅限直流
	IfUpload           int8        //单元16-是否上传主站 0-无 1-有
	IfPay              int8        //单元17-是否付费
	StopCause          int8        //单元18-充电停止原因 0-正常结束 1-异常结束
	ChargeStartTime    string      //单元19-充电开始时间 BCD 7字节
	ChargeStopTime     string      //单元20-充电结束时间 BCD 7字节
	RecordID           uint32       //单元21-记录流水号
	StorageID          uint32       //单元22-记录存储号
	ServiceMoney float64 //服务费金额
	SumMoney float64 //合计金额
	Stage              [30]float64 //10个阶段的充电电量 xx.xx 和充电金额xx.xx、充电服务费xx.xx  0-阶段1电量 1-阶段1 金额 2-阶段2电量 3-阶段2金额 ......18-阶段10 电量 19-阶段10 金额
}

//服务器回应规则
type HistoryReplyPack struct {
	Count     int16 //数据单元个数
	RecordID  uint32 //记录序号
	StorageID uint32 //记录存储号
	Confirm   int32 //后台确认状态 0-正常 1-流水号重复被丢弃 2-其他
}

func (p *HistoryReplyPack) Pack(writer io.Writer) error {
	var err error
	err = binary.Write(writer, binary.LittleEndian, &p.Count)
	err = binary.Write(writer, binary.LittleEndian, &p.RecordID)
	err = binary.Write(writer, binary.LittleEndian, &p.StorageID)
	err = binary.Write(writer, binary.LittleEndian, &p.Confirm)
	return err
}

func (p *HistoryPack) Unpack(reader io.Reader) error {
	var err error
	//数据单元个数
	err = binary.Read(reader, binary.LittleEndian, &p.Count)

	var b [2]byte   //数据单元标识
	var l int8      //数据单元长度
	var mark string //标识字符串
	var bcd [7]byte //bcd 7字节数据
	var n int32     //数据字段 用于读取后计算
	var n16 int16 //数据字段 用于后期数据读取使用
	var temp []byte //临时变长byte数据

	for i := 0; i < int(p.Count); i++ {
		err = binary.Read(reader, binary.LittleEndian, &b)
		mark = hex.EncodeToString(b[:])
		err = binary.Read(reader, binary.LittleEndian, &l)
		switch mark {
		case "0101":
			err = binary.Read(reader, binary.LittleEndian, &p.ChargeMethod)
		case "0201":
			err = binary.Read(reader, binary.LittleEndian, &p.ChargeMode)
		case "0301":
			err = binary.Read(reader, binary.LittleEndian, &p.CardType)
		case "0401": //单元4 20字节用户号
			var u [20]byte
			err = binary.Read(reader, binary.LittleEndian, &u)
			p.UserId= strings.ReplaceAll(string(u[:]),"\x00","")
		case "0501": //单元5 17字节车辆vin 待处理 进行hex编码 已编码
			var v [17]byte
			err = binary.Read(reader, binary.LittleEndian, &v)
			p.CarVin =strings.ReplaceAll(string(v[:]),"\x00","")
		case "0601":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.BeforeSurplusMoney = float64(n) / 100
		case "0701":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeVoltage = float64(n) / 10
		case "0801":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeCurrent = float64(n) / 100
		case "0901":
			err = binary.Read(reader, binary.LittleEndian, &p.ChargeTime)
		case "0a01":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeMoney = float64(n) / 100
		case "0b01":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeAmount = float64(n) / 100
		case "0c01":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.BeforeAmount = float64(n) / 100
		case "0d01":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.StopAmount = float64(n) / 100
		case "0e01":
			err = binary.Read(reader, binary.LittleEndian, &p.SurplusTime)
		case "0f01":
			err = binary.Read(reader, binary.LittleEndian, &p.Soc)
		case "1001":
			err = binary.Read(reader, binary.LittleEndian, &p.IfUpload)
		case "1101":
			err = binary.Read(reader, binary.LittleEndian, &p.IfPay)
		case "1201":
			err = binary.Read(reader, binary.LittleEndian, &p.StopCause)
		case "1301":
			err = binary.Read(reader, binary.LittleEndian, &bcd)
			p.ChargeStartTime = common.Bcd2time(bcd)
		case "1401":
			err = binary.Read(reader, binary.LittleEndian, &bcd)
			p.ChargeStopTime = common.Bcd2time(bcd)
		case "1501":
			err = binary.Read(reader, binary.LittleEndian, &p.RecordID)
		case "1601":
			err = binary.Read(reader, binary.LittleEndian, &p.StorageID)
		case "1701":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ServiceMoney = float64(n) / 100
		case "1801":
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.SumMoney = float64(n) / 100
		case "1901":
			for i1 := 0; i1 < int(l/2); i1++ {
				err = binary.Read(reader, binary.LittleEndian, &n16)
				p.Stage[i1] = float64(n16) / 100
			}
		default:
			temp = make([]byte, l)
			err = binary.Read(reader, binary.LittleEndian, &temp)
		}
	}

	return err
}
